#include <expat.h>
static XML_Parser psr;
#endif
+#include <time.h>
+
+#include "uuid.h"
FILE *fd;
FILE *ofd;
#define MYNAME "coastexp"
#define MY_CBUF 4096
+#define MY_TBUF 64
+#define MY_UBUF 128
#if NO_EXPAT
void
}
#else
+static void *mkshort_handle; // short-name handle
static char *element; // Current element being parsed
static char *cdatastr; // Current XML character data being built up (until a <lf>)
/* CE-specific mark structure - used for both route marks and standalone marks */
struct CE_MARK {
- struct CE_MARK *next; // pointer to next mark in list
+ queue Q;
char *id; // CE's mark ID (of the form "{<guid>}")
- waypoint *wp; // GPSBabel waypoint
+ char *created; // CE's creation time (of the form "<YYYY><MM><DD>T<HH><MM><SS>Z")
+ waypoint *wp; // GPSBabel waypoint
int used; // Is this mark used in a route or not?
};
typedef struct CE_MARK ce_mark;
/* CE-specific route structure */
struct CE_ROUTE {
- struct CE_ROUTE *next; // pointer to next route in list
- char *id; // CE's route ID (of the form "{<guid>}")
+ queue Q;
+ char *id; // CE's route ID (of the form "{<guid>}")
route_head *r; // GPSBabel route header
- ce_mark *marks; // list of CE marks in this route
+ queue ce_mark_head; // list of CE marks in this route
};
typedef struct CE_ROUTE ce_route;
-static ce_route *routes = NULL; // List of routes currently found
+static queue ce_route_head; // List of routes currently found
static ce_route *currentRoute = NULL; // Current route being processed
-static ce_mark *marks = NULL; // List of stand-alone marks currently found
-static ce_mark *currentMark = NULL; // Current mark being processed
-static int inRoute = 0; // Are we processing a route?
-static int inMark = 0; // Are we processing a mark?
+static queue ce_mark_head; // List of stand-alone marks currently found
+static ce_mark *currentMark = NULL; // Current mark being processed
+static char *time_buffer = NULL; // Time buffer for processing times
+static char *uuid_buffer = NULL; // UUID buffer for processing uuid's
+static int inRoute = 0; // Are we processing a route?
+static int inMark = 0; // Are we processing a mark?
/* Add a route to the list of routes */
static void
add_route(ce_route *route)
{
- if (routes == NULL) {
- routes = route;
- } else {
- ce_route *curr = routes;
- while (curr->next != NULL)
- curr = curr->next;
- curr->next = route;
- }
+ ENQUEUE_TAIL(&ce_route_head, &route->Q);
}
/* Add a mark to the list of stand-alone marks */
static void
add_mark(ce_mark *mark)
{
- if (marks == NULL) {
- marks = mark;
- } else {
- ce_mark *curr = marks;
- while (curr->next != NULL)
- curr = curr->next;
- curr->next = mark;
- }
+ ENQUEUE_TAIL(&ce_mark_head, &mark->Q);
}
/* Add a mark to the specified route */
static void
add_mark_to_route(ce_route *route, ce_mark *mark)
{
- if (route->marks == NULL) {
- route->marks = mark;
- } else {
- ce_mark *curr = route->marks;
- while (curr->next != NULL)
- curr = curr->next;
- curr->next = mark;
+ ENQUEUE_TAIL(&route->ce_mark_head, &mark->Q);
+}
+
+/* Free a mark */
+static void
+free_mark(ce_mark *mark)
+{
+ xfree(mark->id);
+ if (mark->created)
+ xfree(mark->created);
+ xfree(mark);
+}
+
+/* Free a route */
+static void
+free_route(ce_route *route)
+{
+ queue *elem, *tmp;
+ QUEUE_FOR_EACH(&route->ce_mark_head, elem, tmp) {
+ ce_mark *mark = (ce_mark *) elem;
+ free_mark(mark);
}
+ xfree(route->id);
+ xfree(route);
+ // Don't free the waypoint since this is done elsewhere
}
/* Start processing an XML item */
static void
ce_start(void *data, const char *el, const char **attr)
{
- element = xstrdup(el);
+ const char **ap;
+ strcpy(element, el);
if (0 == strcmp(el, "Route")) {
inRoute = 1;
- const char **ap;
for (ap = attr; *ap; ap+=2) {
if (0 == strcmp(ap[0], "id")) {
// Create a CE route object and add it to the list of routes
currentRoute = (ce_route *) xcalloc(sizeof (ce_route), 1);
- currentRoute->next = NULL;
currentRoute->id=xstrdup(ap[1]);
currentRoute->r = route_head_alloc();
- currentRoute->marks = NULL;
+ QUEUE_INIT(¤tRoute->ce_mark_head);
add_route(currentRoute);
}
}
} else if (0 == strcmp(el, "Mark")) {
inMark = 1;
- const char **ap;
+ currentMark = (ce_mark *) xcalloc(sizeof (ce_mark), 1);
+ currentMark->wp = NULL;
+ currentMark->used = 0;
+ add_mark(currentMark);
for (ap = attr; *ap; ap+=2) {
if (0 == strcmp(ap[0], "id")) {
// Create a CE mark object and add it to the list of stand-alone marks
- currentMark = (ce_mark *) xcalloc(sizeof (ce_mark), 1);
- currentMark->next = NULL;
- currentMark->id=xstrdup(ap[1]);
- currentMark->wp = NULL;
- currentMark->used = 0;
- add_mark(currentMark);
+ currentMark->id = xstrdup(ap[1]);
+ }
+ else if (0 == strcmp(ap[0], "created")) {
+ currentMark->created = xstrdup(ap[1]);
}
}
}
ce_cdata(void *dta, const XML_Char *s, int len)
{
if (*s != '\n') {
+ char *edatastr;
// We buffer up characters in 'cdatastr' until a single <lf> is received
if ((strlen(cdatastr) + len) > MY_CBUF) {
printf("Buffer overflow - line too long!");
exit(-1);
}
- char *edatastr = cdatastr+strlen(cdatastr);
+ edatastr = cdatastr+strlen(cdatastr);
memcpy(edatastr, s, len);
edatastr[len] = '\0';
} else {
if (strlen(s) <= 0)
return;
if (0 == strcmp(element, "Marks")) {
- if (inRoute == 1) {
+ if (inRoute) {
// We are processing the marks in a route so create a CE mark object
// and add it to the current route
ce_mark *mark = (ce_mark *) xcalloc(sizeof (ce_mark), 1);
- mark->next = NULL;
mark->id = xstrdup(s);
+ mark->created = NULL;
mark->wp = NULL;
add_mark_to_route(currentRoute, mark);
}
} else if (0 == strcmp(element, "Position")) {
- if (inMark == 1) {
+ if (inMark) {
// We are processing a standalone mark so read the lat/long position
// and create a waypoint to add to the current mark
char *position = xstrdup(s);
char *lat = position;
char *latNorS = position;
+ char *lng;
+ char *longEorW;
while (*latNorS != ' ')
latNorS++;
*latNorS++ = '\0';
- char *lng = latNorS;
+ lng = latNorS;
lng++; lng++;
- char *longEorW = lng;
+ longEorW = lng;
while (*longEorW != ' ')
longEorW++;
*longEorW++ = '\0';
- currentMark->wp = waypt_new();
+ if (!currentMark->wp)
+ currentMark->wp = waypt_new();
currentMark->wp->latitude = atof(lat);
if (*latNorS == 'S')
currentMark->wp->latitude = -currentMark->wp->latitude;
currentMark->wp->longitude = atof(lng);
if (*longEorW == 'W')
currentMark->wp->longitude = -currentMark->wp->longitude;
+ xfree(position);
}
} else if (0 == strcmp(element, "Name")) {
// Names we care about may be either for routes or marks
- char *name = xstrdup(s);
- if (inMark == 1)
- currentMark->wp->shortname = name;
- else if (inRoute == 1)
- currentRoute->r->rte_name = name;
+ if (inMark)
+ {
+ if (!currentMark->wp)
+ currentMark->wp = waypt_new();
+ currentMark->wp->shortname = xstrdup(s);
+
+ // Also set the creation time
+ if (currentMark->created)
+ {
+ struct tm t;
+ char yearString[5], monthString[3], dayString[3], hourString[3], minString[3], secString[3];
+ memset(&t, 0, sizeof(struct tm));
+ strncpy(yearString, currentMark->created, 4);
+ yearString[4] = '\0';
+ t.tm_year = atoi(yearString) - 1900;
+ strncpy(monthString, currentMark->created+4, 2);
+ monthString[3] = '\0';
+ t.tm_mon = atoi(monthString) - 1;
+ strncpy(dayString, currentMark->created+6, 2);
+ dayString[3] = '\0';
+ t.tm_mday = atoi(dayString);
+ strncpy(hourString, currentMark->created+9, 2);
+ hourString[3] = '\0';
+ t.tm_hour = atoi(hourString);
+ strncpy(minString, currentMark->created+11, 2);
+ minString[3] = '\0';
+ t.tm_min = atoi(minString);
+ strncpy(secString, currentMark->created+13, 2);
+ secString[3] = '\0';
+ t.tm_sec = atoi(secString);
+ currentMark->wp->creation_time = mktime(&t);
+ }
+ }
+ else if (inRoute)
+ currentRoute->r->rte_name = xstrdup(s);
} else if (0 == strcmp(element, "Description")) {
// Descriptions we care about may be either for routes or marks
char *desc = xstrdup(s);
- if (inMark == 1)
+ if (inMark)
+ {
+ if (!currentMark->wp)
+ currentMark->wp = waypt_new();
currentMark->wp->description = desc;
- else if (inRoute == 1)
+ }
+ else if (inRoute)
currentRoute->r->rte_desc = desc;
}
ce_rd_init(const char *fname)
{
fd = xfopen(fname, "r", MYNAME);
+ QUEUE_INIT(&ce_route_head);
+ QUEUE_INIT(&ce_mark_head);
psr = XML_ParserCreate(NULL);
if (!psr) {
XML_SetElementHandler(psr, ce_start, ce_end);
cdatastr = xcalloc(MY_CBUF,1);
+ element = xcalloc(MY_CBUF,1);
XML_SetCharacterDataHandler(psr, ce_cdata);
}
void
ce_fix_waypoints(void)
{
- ce_route *route = routes;
- while (route != NULL) {
- ce_mark *mark = route->marks;
- while (mark != NULL) {
- ce_mark *mark2 = marks;
- while (mark2 != NULL) {
+ queue *elem, *tmp;
+ QUEUE_FOR_EACH(&ce_route_head, elem, tmp) {
+ ce_route *route = (ce_route *) elem;
+ queue *elem2, *tmp2;
+ QUEUE_FOR_EACH(&route->ce_mark_head, elem2, tmp2) {
+ ce_mark *mark = (ce_mark *) elem2;
+ queue *elem3, *tmp3;
+ QUEUE_FOR_EACH(&ce_mark_head, elem3, tmp3) {
+ ce_mark *mark2 = (ce_mark *) elem3;
if (0 == strcmp(mark->id, mark2->id)) {
- mark->wp = mark2->wp;
+ mark->wp = waypt_dupe(mark2->wp);
mark2->used = 1;
break;
}
- mark2 = mark2->next;
}
- mark = mark->next;
}
- route = route->next;
}
}
void
ce_check_route_names(void)
{
- ce_route *route = routes;
- while (route != NULL) {
+ queue *elem, *tmp;
+ QUEUE_FOR_EACH(&ce_route_head, elem, tmp) {
+ ce_route *route = (ce_route *) elem;
if (route->r->rte_name == NULL) {
- cdatastr = '\0';
- strcat(cdatastr, marks->wp->shortname);
+ *cdatastr = '\0';
+ strcat(cdatastr, ((ce_mark *) QUEUE_FIRST(&route->ce_mark_head))->wp->shortname);
strcat(cdatastr, "->");
- ce_mark *mark = route->marks;
- while (mark->next != NULL)
- mark = mark->next;
- strcat(cdatastr, mark->wp->shortname);
+ strcat(cdatastr, ((ce_mark *) QUEUE_LAST(&route->ce_mark_head))->wp->shortname);
route->r->rte_name = xstrdup(cdatastr);
}
- route = route->next;
}
}
void
ce_remove_unused_marks(void)
{
- ce_mark *mark = marks;
- ce_mark *prev_mark = NULL;
- while (mark != NULL) {
- if (mark->used == 1) {
- if (prev_mark == NULL)
- marks = mark = mark->next;
- else
- prev_mark->next = mark = mark->next;
- continue;
+ queue *elem, *tmp;
+ QUEUE_FOR_EACH(&ce_mark_head, elem, tmp) {
+ ce_mark *mark = (ce_mark *) elem;
+ if (mark->used)
+ {
+ dequeue(elem);
+ if (mark->wp)
+ waypt_free(mark->wp);
+ free_mark(mark);
}
- prev_mark = mark;
- mark = mark->next;
}
}
void
ce_print_results(void)
{
- ce_route *curr_route = routes;
- while (curr_route != NULL) {
- printf("Route name=%s id=%s\n", curr_route->r->rte_name, curr_route->id);
- ce_mark *curr_mark = curr_route->marks;
- while (curr_mark != NULL) {
- if (curr_mark->wp == NULL)
+ queue *elem, *tmp;
+ QUEUE_FOR_EACH(&ce_route_head, elem, tmp) {
+ queue *elem2, *tmp2;
+ ce_route *route = (ce_route *) elem;
+ printf("Route name=%s id=%s\n", route->r->rte_name, route->id);
+ QUEUE_FOR_EACH(&route->ce_mark_head, elem2, tmp2) {
+ ce_mark *mark = (ce_mark *) elem2;
+ if (mark->wp == NULL)
printf(" null\n");
else
- printf(" %s (%f, %f)\n", curr_mark->wp->shortname, curr_mark->wp->latitude, curr_mark->wp->longitude);
- curr_mark = curr_mark->next;
+ printf(" %s (%f, %f)\n", mark->wp->shortname, mark->wp->latitude, mark->wp->longitude);
}
- curr_route = curr_route->next;
}
- ce_mark *curr_mark = marks;
- while (curr_mark != NULL) {
- printf("Mark name=%s id=%s ", curr_mark->wp->shortname, curr_mark->id);
- if (curr_mark->wp == NULL)
+
+ QUEUE_FOR_EACH(&ce_mark_head, elem, tmp) {
+ ce_mark *mark = (ce_mark *) elem;
+ printf("Mark name=%s id=%s ", mark->wp->shortname, mark->id);
+ if (mark->wp == NULL)
printf("(null)\n");
else
- printf("(%f, %f)\n", curr_mark->wp->latitude, curr_mark->wp->longitude);
- curr_mark = curr_mark->next;
+ printf("(%f, %f)\n", mark->wp->latitude, mark->wp->longitude);
}
}
void
ce_rd_deinit(void)
{
+ queue *elem, *tmp;
+
ce_fix_waypoints();
ce_check_route_names();
ce_remove_unused_marks();
// ce_print_results();
// Add routes to GPSBabel
- ce_route *route = routes;
- while (route != NULL) {
+ QUEUE_FOR_EACH(&ce_route_head, elem, tmp) {
+ ce_route *route = (ce_route *) elem;
+ queue *elem2, *tmp2;
route_add_head(route->r);
- ce_mark *mark = route->marks;
- while (mark->next != NULL) {
- route_add_wpt(route->r, mark->wp);
- mark = mark->next;
+ QUEUE_FOR_EACH(&route->ce_mark_head, elem2, tmp2) {
+ ce_mark *mark = (ce_mark *) elem2;
+ if (mark->wp)
+ route_add_wpt(route->r, mark->wp);
+ else
+ printf("Undefined mark: %s\n", mark->id);
}
- route = route->next;
+ free_route(route);
}
// Add (unused) marks to GPSBabel
- ce_mark *mark = marks;
- while (mark != NULL) {
+ QUEUE_FOR_EACH(&ce_mark_head, elem, tmp) {
+ ce_mark *mark = (ce_mark *) elem;
waypt_add(mark->wp);
- mark = mark->next;
+ free_mark(mark);
}
fclose(fd);
+ xfree(element);
+ xfree(cdatastr);
}
void
ce_wr_init(const char *fname)
{
- fatal(MYNAME ": Does not support writing CoastalExplorer files.\n");
+ mkshort_handle = mkshort_new_handle();
+ QUEUE_INIT(&ce_mark_head);
+ time_buffer = xcalloc(MY_TBUF,1);
+ uuid_buffer = xcalloc(MY_UBUF,1);
+
ofd = xfopen(fname, "w", MYNAME);
}
ce_wr_deinit(void)
{
fclose(ofd);
+ mkshort_del_handle(mkshort_handle);
+ xfree(time_buffer);
+ xfree(uuid_buffer);
+}
+
+static char *
+ce_gen_creation_time(time_t tm)
+{
+ struct tm *t = localtime(&tm);
+ sprintf(time_buffer, "%04d%02d%02dT%02d%02d%02dZ", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
+ return time_buffer;
+}
+
+static char *
+ce_gen_current_time(void)
+{
+ return ce_gen_creation_time(current_time());
+}
+
+static char *
+ce_gen_uuid(void)
+{
+ uuid_t uu;
+ uuid_generate(uu);
+ sprintf(uuid_buffer, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7],
+ uu[8], uu[9], uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
+ return uuid_buffer;
+}
+
+static void
+ce_route_hdr(const route_head *rte)
+{
+ fprintf(ofd, "\t<Route created=\"%s\" id=\"{%s}\">\n", ce_gen_current_time(), ce_gen_uuid());
+ fprintf(ofd, "\t\t<Marks>\n");
+}
+
+static void
+ce_route_disp(const waypoint *waypointp)
+{
+ char *uuid = ce_gen_uuid();
+ char *id = xcalloc(strlen(uuid)+3, 1);
+ sprintf(id, "{%s}", uuid);
+ currentMark = (ce_mark *) xcalloc(sizeof (ce_mark), 1);
+ currentMark->id = id;
+ currentMark->wp = (waypoint *) waypointp;
+ ENQUEUE_TAIL(&ce_mark_head, ¤tMark->Q);
+ fprintf(ofd, "\t\t\t%s\n", id);
+}
+
+static void
+ce_route_tlr(const route_head *rte)
+{
+ fprintf(ofd, "\t\t</Marks>\n");
+ if (rte->rte_name)
+ fprintf(ofd, "\t\t<Name>%s</Name>\n", rte->rte_name);
+ fprintf(ofd, "\t</Route>\n");
+}
+
+static void
+ce_waypt_pr(const waypoint *waypointp)
+{
+}
+
+static void
+ce_mark_pr(void)
+{
+ queue *elem, *tmp;
+ QUEUE_FOR_EACH(&ce_mark_head, elem, tmp) {
+ ce_mark *mark = (ce_mark *) elem;
+ double latitude = mark->wp->latitude;
+ char NorS = 'N';
+ char EorW = 'E';
+ double longitude = mark->wp->longitude;
+ fprintf(ofd, "\t<Mark created=\"%s\" id=\"%s\">\n", ce_gen_creation_time(mark->wp->creation_time), mark->id);
+ if (latitude < 0) {
+ latitude = -latitude;
+ NorS = 'S';
+ }
+ if (longitude < 0) {
+ longitude = -longitude;
+ EorW = 'W';
+ }
+ fprintf(ofd, "\t\t<Position>%3.6f %c %3.6f %c</Position>\n", latitude, NorS, longitude, EorW);
+ if (mark->wp->shortname)
+ fprintf(ofd, "\t\t<Name>%s</Name>\n", mark->wp->shortname);
+ fprintf(ofd, "\t</Mark>\n");
+ free_mark(mark);
+ }
}
void
ce_write(void)
{
+ setshort_whitespace_ok(mkshort_handle, 0);
+ setshort_length(mkshort_handle, 32);
+
+ fprintf(ofd, "<?xml version=\"1.0\"?>\n");
+ fprintf(ofd, "<NavObjectCollection created=\"%s\"\n", ce_gen_current_time());
+ fprintf(ofd, "\t<Name>Navigation Objects</Name>\n");
+
+ route_disp_all(ce_route_hdr, ce_route_tlr, ce_route_disp);
+ ce_mark_pr();
+ waypt_disp_all(ce_waypt_pr);
+
+ fprintf(ofd, "</NavObjectCollection>\n");
}
ff_vecs_t coastexp_vecs = {
<time>1970-01-01T00:00:00Z</time>
<bounds minlat="34.019184000" minlon ="-122.441589000" maxlat="37.229349000" maxlon="-120.438209000" />
<wpt lat="37.229349000" lon="-122.441589000">
+<time>2004-11-06T05:13:00Z</time>
<name>PESCDR01</name>
<cmt>PESCDR01</cmt>
<desc>PESCDR01</desc>
</wpt>
<wpt lat="37.183397000" lon="-122.411904000">
+<time>2004-11-06T05:13:24Z</time>
<name>PIGEON01</name>
<cmt>PIGEON01</cmt>
<desc>PIGEON01</desc>
</wpt>
<wpt lat="37.090736000" lon="-122.348775000">
+<time>2004-11-06T05:13:41Z</time>
<name>ANONUV01</name>
<cmt>ANONUV01</cmt>
<desc>ANONUV01</desc>
</wpt>
<wpt lat="36.929502000" lon="-122.113725000">
+<time>2004-11-06T05:14:09Z</time>
<name>SCRUZ01</name>
<cmt>SCRUZ01</cmt>
<desc>SCRUZ01</desc>
</wpt>
<wpt lat="36.934235000" lon="-122.022130000">
+<time>2004-11-06T05:14:16Z</time>
<name>SCRUZ02</name>
<cmt>SCRUZ02</cmt>
<desc>SCRUZ02</desc>
</wpt>
<wpt lat="36.960666000" lon="-122.024734000">
+<time>2004-11-06T05:14:20Z</time>
<name>SCRUZENT</name>
<cmt>SCRUZENT</cmt>
<desc>SCRUZENT</desc>
</wpt>
<wpt lat="36.581344000" lon="-121.995411000">
+<time>2004-11-06T05:24:22Z</time>
<name>CYPRSSPT</name>
<cmt>CYPRSSPT</cmt>
<desc>CYPRSSPT</desc>
</wpt>
<wpt lat="36.301110000" lon="-121.919097000">
+<time>2004-11-06T05:24:38Z</time>
<name>PTSUR</name>
<cmt>PTSUR</cmt>
<desc>PTSUR</desc>
</wpt>
<wpt lat="36.238177000" lon="-121.855209000">
+<time>2004-11-06T05:25:15Z</time>
<name>COOPERPT</name>
<cmt>COOPERPT</cmt>
<desc>COOPERPT</desc>
</wpt>
<wpt lat="36.225175000" lon="-121.801314000">
+<time>2004-11-06T05:25:26Z</time>
<name>PFEIFENT</name>
<cmt>PFEIFENT</cmt>
<desc>PFEIFENT</desc>
</wpt>
<wpt lat="36.230449000" lon="-121.797444000">
+<time>2004-11-06T05:25:31Z</time>
<name>PFEIFANC</name>
<cmt>PFEIFANC</cmt>
<desc>PFEIFANC</desc>
</wpt>
<wpt lat="35.879801000" lon="-121.498947000">
+<time>2004-11-06T05:28:26Z</time>
<name>SANMRT01</name>
<cmt>SANMRT01</cmt>
<desc>SANMRT01</desc>
</wpt>
<wpt lat="35.652801000" lon="-121.308485000">
+<time>2004-11-06T05:28:33Z</time>
<name>PDRSBLNC</name>
<cmt>PDRSBLNC</cmt>
<desc>PDRSBLNC</desc>
</wpt>
<wpt lat="35.623297000" lon="-121.185920000">
+<time>2004-11-06T05:28:50Z</time>
<name>SNSMNENT</name>
<cmt>SNSMNENT</cmt>
<desc>SNSMNENT</desc>
</wpt>
<wpt lat="35.640478000" lon="-121.183772000">
+<time>2004-11-06T05:28:53Z</time>
<name>SNSMNANC</name>
<cmt>SNSMNANC</cmt>
<desc>SNSMNANC</desc>
</wpt>
<wpt lat="35.572353000" lon="-121.152797000">
+<time>2004-11-06T05:36:18Z</time>
<name>CAMBRIA</name>
<cmt>CAMBRIA</cmt>
<desc>CAMBRIA</desc>
</wpt>
<wpt lat="35.449214000" lon="-121.020825000">
+<time>2004-11-06T05:36:26Z</time>
<name>PTESTERO</name>
<cmt>PTESTERO</cmt>
<desc>PTESTERO</desc>
</wpt>
<wpt lat="35.216602000" lon="-120.928391000">
+<time>2004-11-06T05:36:35Z</time>
<name>PTBUCHON</name>
<cmt>PTBUCHON</cmt>
<desc>PTBUCHON</desc>
</wpt>
<wpt lat="34.883361000" lon="-120.684631000">
+<time>2004-11-06T05:36:42Z</time>
<name>PTSAL01</name>
<cmt>PTSAL01</cmt>
<desc>PTSAL01</desc>
</wpt>
<wpt lat="34.884641000" lon="-120.652026000">
+<time>2004-11-06T05:36:47Z</time>
<name>PTSALENT</name>
<cmt>A description of the Point Sal Entrance mark</cmt>
<desc>A description of the Point Sal Entrance mark</desc>
</wpt>
<wpt lat="34.896555000" lon="-120.649124000">
+<time>2004-11-06T05:37:04Z</time>
<name>PTSALANC</name>
<cmt>PTSALANC</cmt>
<desc>PTSALANC</desc>
</wpt>
<wpt lat="34.758180000" lon="-120.642516000">
+<time>2004-11-06T05:39:49Z</time>
<name>PURSMAPT</name>
<cmt>PURSMAPT</cmt>
<desc>PURSMAPT</desc>
</wpt>
<wpt lat="34.572579000" lon="-120.663636000">
+<time>2004-11-06T05:39:54Z</time>
<name>PTARGLLO</name>
<cmt>PTARGLLO</cmt>
<desc>PTARGLLO</desc>
</wpt>
<wpt lat="34.113844000" lon="-120.492630000">
+<time>2004-11-06T05:40:05Z</time>
<name>SANMGL01</name>
<cmt>SANMGL01</cmt>
<desc>SANMGL01</desc>
</wpt>
<wpt lat="34.029483000" lon="-120.471409000">
+<time>2004-11-06T05:40:44Z</time>
<name>SANMGL02</name>
<cmt>SANMGL02</cmt>
<desc>SANMGL02</desc>
</wpt>
<wpt lat="34.019184000" lon="-120.444197000">
+<time>2004-11-06T05:40:48Z</time>
<name>SANMGL03</name>
<cmt>SANMGL03</cmt>
<desc>SANMGL03</desc>
</wpt>
<wpt lat="34.023478000" lon="-120.438209000">
+<time>2004-11-06T05:40:57Z</time>
<name>ADCOVENT</name>
<cmt>ADCOVENT</cmt>
<desc>ADCOVENT</desc>
</wpt>
<wpt lat="34.028615000" lon="-120.439696000">
+<time>2004-11-06T05:40:59Z</time>
<name>ADCOVANC</name>
<cmt>ADCOVANC</cmt>
<desc>ADCOVANC</desc>
<rte>
<name>Into The Bay</name>
<rtept lat="37.763290" lon="-122.282580">
+<time>2004-11-06T01:09:09Z</time>
<name>SFBALBAY</name>
</rtept>
<rtept lat="37.751613" lon="-122.339028">
+<time>2004-11-06T01:09:10Z</time>
<name>SFBAY001</name>
</rtept>
<rtept lat="37.817420" lon="-122.394305">
+<time>2004-11-06T01:09:13Z</time>
<name>SFBAY002</name>
</rtept>
<rtept lat="37.819339" lon="-122.478302">
+<time>2004-11-06T01:09:16Z</time>
<name>SFGGBRDG</name>
</rtept>
<rtept lat="37.773033" lon="-122.605838">
+<time>2004-11-06T01:09:20Z</time>
<name>SFCHNL01</name>
</rtept>
<rtept lat="37.518860" lon="-122.529914">
+<time>2004-11-06T01:09:26Z</time>
<name>HMCOLREF</name>
</rtept>
<rtept lat="37.482348" lon="-122.507704">
+<time>2004-11-06T01:09:27Z</time>
<name>HMPILL01</name>
</rtept>
<rtept lat="37.475062" lon="-122.488531">
+<time>2004-11-06T05:16:24Z</time>
<name>HMPILLPT</name>
</rtept>
<rtept lat="37.476448" lon="-122.475800">
+<time>2004-11-06T01:09:29Z</time>
<name>HMPILL02</name>
</rtept>
+ <rtept lat="37.495102" lon="-122.483927">
+<time>2004-11-06T01:09:30Z</time>
+ <name>HMPILL03</name>
+ </rtept>
</rte>
</gpx>